<?php
/**
 * tools
 *
 * @version:	0.1
 * @package:	core
 * @author:		alex_ez
 * @created:	26 jan 2011
 *
 * @copyright:	(c) 2008-2011 alex yaroshevich
 */

function mb_ucfirst($string) {
	return mb_strtoupper(mb_substr($string, 0, 1)) . mb_substr($string, 1);
}

function is_map(&$A) {
	if (empty($A) || !is_array($A))
		return null;

	$l = sizeof($A)-1;
	// first and last are numeric
	if (!isset($A[0]) || !isset($A[$l]))
		return true;

	//if (join(',',array_keys($A)) == join(',',range(0,sizeof($A)-1)))
	//	return true;
	for($i=1, $l=$l; $i<$l; $i++)
		if(!isset($A[$i]))
			return true;

	return false;
}

function is_list(&$A) {
	if (empty($A) || !is_array($A))
		return null;

	return !is_map($A);
}

function is_list_of_maps(&$A) {
	if (empty($A) || !is_array($A))
		return null;

	if (!is_list($A))
		return false;

	for($i=0,$l=sizeof($A);$i<$l;$i++)
		if(!is_map($A[$i]))
			return false;

	return true;
}

function is_array_of_maps(&$A) {
	if (empty($A) || !is_array($A))
		return null;

	foreach(array_keys($A) as $i)
		if(!is_map($A[$i]))
			return false;

	return true;
}

function is_list_of_numerics(&$A) {
	if (empty($A) || !is_array($A))
		return null;

	if (!is_list($A))
		return false;

	for($i=0,$l=sizeof($A);$i<$l;$i++)
		if(!is_numeric($A[$i]))
			return false;

	return true;
}

function is_array_of_numerics(&$A) {
	if (empty($A) || !is_array($A))
		return null;

	foreach(array_keys($A) as $i)
		if(!is_numeric($A[$i]))
			return false;

	return true;
}


function parse_args($args, $defaults = false)
{
	$r = array();

	if ( is_object( $args ) )
		$r = get_object_vars( $args );
	elseif ( is_array( $args ) )
		$r =& $args;
	else
		parse_str( $args, $r );

	if(is_array( $defaults))
		return $r + $defaults;

	return $r;
}

function extract_args($args, $defaults)
{
	$rslt = array();

	$options = parse_args($args, $defaults);

	if(is_array($defaults))
		foreach(array_keys($defaults) as $key)
			$rslt[$key] = $options[$key];

	return $rslt;
}

function pick( )
{
	$_A = func_get_args();
	if( sizeof( $_A ) == 1 && is_array( reset( $_A ) ) ) $_A = reset( $_A );
	
	foreach( array_keys( $_A ) as $k )
	if( isset( $_A[$k] )
	 && !is_null( $_A[$k] ) )
		return $_A[$k];
	
	return null;
}
	
function pick_any( )
{
	$_A = func_get_args();
	if( sizeof( $_A ) < 1 ) return null;
	
	return $_A[ rand( 0, sizeof( $_A )-1 ) ];
}
	
function plural( )
{
	$args = func_get_args( );
	$f = array_shift( $args );
	if(!is_array($f)) {
		$f = array( $f );
		while( !is_numeric( reset( $args ) ) && !empty( $args ) )
			$f[] = array_shift( $args );
	}
	$n = array_shift( $args );

	$plural_forms = array(
	'ru' => array(
		'nplurals' => 3,
		'plural' => '( (n%10)==1 && (n%100)!=11 ) ? 0 : ( n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2 )'
		),
	);

	$l = 'ru';
	$ff = create_function( '$n', 'return '.str_replace( 'n', '$n', $plural_forms[$l]['plural'] ).';' );
	$m = $ff( $n );
	$r = !isset( $f[ $m ] ) ? $f[ $m ] : reset( $f );

	return $f[ $m ];
}

function pluraltext_ru( $n, $s = 'm', $st = null )
{
	if( !ctype_digit( (string)($n) )
		|| (!empty($st) && sizeof($st) != 3)
		|| !is_string($s) || isset($s[7]) )
		return null;

	$zero = 'ноль';
	$onesbysex = array(
		'm' => array('','один','два','три','четыре','пять','шесть','семь','восемь','девять','десять','одиннадцать','двенадцать','тринадцать','четырнадцать','пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать'),
		'f' => array(1=>'одна','две'),'b' => array(1=>'одно'));
	$onesbysex['f'] = $onesbysex['f'] + $onesbysex['m'];
	$onesbysex['b'] = $onesbysex['b'] + $onesbysex['m'];
	
	$s = !isset($onesbysex[$s]) ? 'm' : $s;
	$decs = array('','десять','двадцать','тридцать','сорок','пятьдесят','шестьдесят','семьдесят','восемьдесят','девяносто');
	$huns = array('','сто','двести','триста','четыреста','пятьсот','шестьсот','семьсот','восемьсот','девятьсот');

	$sexes = array( $s, 'f', 'm', 'm', 'm' );
	$grades = array(
		0 => is_array($st) ? $st : '',
		1 => array('тысяча','тысячи','тысяч'),
		2 => array('миллион','миллиона','миллионов'),
		3 => array('миллиард','миллиарда','миллиардов'),
		4 => array('триллион','триллиона','триллионов'),
		);

	$n = ltrim($n,'0');
	if(empty($n))
		return $zero;
	
	// normalize
	$n = str_repeat('0',(18-strlen($n))%3) . $n;
	$na = str_split($n, 3);
	
	$r = '';
	$grade = strlen($n)/3;
	foreach( $na as $npart )
	{
		$grade--;
		$ones = $onesbysex[$sexes[$grade]];

		if( $npart[0] )
		$r .= $huns[$npart[0]].' ';

		$nr = (int)(substr($npart,1));
		//var_dump($npart.' '.$nr);
		$r .= isset($ones[$nr])
			? $ones[$nr] . ' '
			: $decs[$npart[1]] . ' ' . $ones[$npart[2]] . ' ';

		if( isset( $grades[$grade] ) && $grades[$grade] )
			$r .= self::plural($grades[$grade],$npart) . ' ';
	}
	
	return rtrim( $r, ' ' );
}

function _test_pluraltext_ru( )
{
	$items = array(
		'm' => array('рубль','рубля','рублей'),
		'f' => array('копейка','копейки','копеек'),
		'b' => array('солнышко','солнышка','солнышек'),
		);
	echo 4321 . ' -> ' . tool::pluraltext_ru(4321,'b',$items['b']) . ' <br/>';
	foreach( range(0,100) as $number )
	{
		$number = rand(500,50000000);
		$qual = tool::pick_any('f','m','b');
		echo $number . ' -> ' . tool::pluraltext_ru($number,$qual,$items[$qual]) . ' <br/>';
	}
	die;
}



/**
 * Substitution
 */
function subst( $pattern, $fields, $wrapper = ':%s' )
{
	if(!is_array($fields)) return $pattern;
	uksort($fields,create_function('$a,$b','return strlen($a)<strlen($b);'));
	return str_replace(
		array_map( create_function( '$a', 'return sprintf("'.$wrapper.'",$a);' ), array_keys( $fields ) ),
		array_map( 'strval', array_values( $fields ) ),
		$pattern );
}

function replace_pattern($str, $vars) {
	return str_replace(array_map( create_function( '$a', 'return ":" . $a;' ), array_keys($vars)), array_values($vars), $str);
}



/* HTTP query functions */

/**
 * Parse query key string to list without syntax analizer
 *
 * @param string $s a[b][c]
 * @return array array('a','b','c')
 */
function parse_str_key($s) {
	if (!is_string($s))
		return null;

	$s = ltrim($s,'?& ');
	if (strpos($s,'=')!==false)
		$s = substr($s,0,strpos($s,'='));
	if (strpos($s,'&')!==false)
		$s = substr($s,0,strpos($s,'&'));

	if(empty($s))
		return array();

	return explode('[',str_replace(array('][',']'),'[',$s));
}


/**
 * Upload errors
 */
function is_upload_error($file, $ignore_no_file = true) {

	if(empty($file))
		$file = UPLOAD_ERR_NO_FILE;

	$errnum = is_array($file) ? (isset($file['error']) ? $file['error'] : UPLOAD_ERR_NO_FILE) : (int)$file;

	if($ignore_no_file) {
		return !($errnum == UPLOAD_ERR_NO_FILE || $errnum == UPLOAD_ERR_OK);
	}

	return $errnum != UPLOAD_ERR_OK;
}

function upload_error($file) {
	
	$errors = array(
		UPLOAD_ERR_OK => __('There is no error, the file uploaded with success.'),
		UPLOAD_ERR_INI_SIZE => __('The uploaded file is too big.'),
		UPLOAD_ERR_FORM_SIZE => __('The uploaded file is too big.'),
		UPLOAD_ERR_PARTIAL => __('The uploaded file was only partially uploaded.'),
		UPLOAD_ERR_NO_FILE => __('No file was uploaded.'),
		UPLOAD_ERR_NO_TMP_DIR => __('Missing a temporary folder.'),
		UPLOAD_ERR_CANT_WRITE => __('Failed to write file to disk.'),
		UPLOAD_ERR_EXTENSION => __('A PHP extension stopped the file upload. ')
	);

	$errnum = is_array($file) ? (isset($file['error']) ? $file['error'] : 0) : (int)$file;

	return isset($errors[$errnum]) ? $errors[$errnum] : '';
}

function is_image($file) {
	if (!file_exists($file) || !is_readable($file))
		return null;

	$size = getimagesize($file);
	if (!$size)
		return false;

	return true;
}
